


#include <stdint.h>
#include <stdio.h>

#include "compiler.h"
#include "hcb_comn.h"
#include "sf.h"



static uint32_t  spage = 0;
static uint32_t  sblck = 0;



static inline void sf_inst_fifo_mod(uint32_t *inst, uint32_t size)
{
	*inst = (*inst & (~(0x000ffff0UL))) | ((size&0xffff)<<4);
}
static inline void sf_inst_tmp_set(uint32_t *inst, uint32_t val, int size)
{
	*inst = (*inst & (~(0x00fffff0UL))) | ((val&0xffff)<<8) | ((size&0xf)<<4);
}
static inline void sf_inst_reg_set_bytes(uint32_t *inst, int size)
{
	*inst = (*inst & (~(0x00000ff0UL))) | ((size&0xf)<<4);
}


int  nor_flash_page_read( uint32_t faddr, uint8_t * buf )
{
	int ret;

	/* set reg, change addr */
	sf_reg_write( 0, faddr );
	sf_reg_write( 1, 0 );
	sf_reg_write( 2, 0 );
	sf_reg_write( 3, 0 );

	ret = sf_sync_start_read( 0, buf, spage );
	if ( ret != 0 )
	{
		return ret;
	}

	return 0;
}


int  nor_flash_unlock( void )
{
	int ret;

	/**/
	ret = sf_sync_start_nofifo( 41 );
	if(ret != 0)
	{
		return ret;
	}

	return 0;
}


int  nor_flash_lock( void )
{
	int ret;

	ret = sf_sync_start_nofifo( 29 );
	if ( ret != 0 )
	{
		return ret;
	}

	return 0;
}


/*faddr are supposed to be aligned to sector size(4K)*/
int  nor_flash_sector_erase( uint32_t faddr )
{
	int ret;

	/*change addr*/
	sf_reg_write( 0, faddr);
	sf_reg_write( 1, 0 );
	sf_reg_write( 2, 0 );
	sf_reg_write( 3, 0 );
	
	/*erase*/
	ret = sf_sync_start_nofifo( 4 );
	if ( ret != 0 )
	{
		return ret;
	}
	
	/* delay, wait finish ?? */
	return 0;
}


int  nor_flash_page_prog( uint32_t faddr, uint8_t * buf )
{
	int ret;

	/**/
	sf_reg_write(0, faddr);
	
	/**/
	ret = sf_sync_start_write( 16, buf, spage );
	if ( ret != 0 )
	{
		//printf("flash erase error!\n");
		return ret;
	}
	
	/**/
	return 0;
}


/* spi-flash， 模块中最多容纳 64 条指令. */

static  uint32_t  insts[] = {
	0x10000310, 0x00000033, 0x20001002, 0x0000000f,			/* 0, read, 4 word */

 	0x30000610, 0x00000ff6, 0x10002010, 0x20000033,			/* 4, erase, 12 word */
	0x000fff06, 0x10000510, 0x20000111, 0x00001228,
	0x0effff27, 0x0f0f0ff7, 0x08000117, 0x0000000f,

	0x30000610, 0x00000ff6, 0x10000210, 0x00000033,			/* 16, prog, 13 word */
	0x20001004, 0x00007d06, 0x10000510, 0x20000111,
	0x00001228, 0x1bffff27, 0x1c0f0ff7, 0x15000117,
	0x0000000f,

	0x30000610, 0x00000ff6, 0x10000110, 0x20003c10,			/* 29, lock, 12 word */
	0x00027106, 0x10000510, 0x20000111, 0x00001228,
	0x27ffff27, 0x280f0ff7, 0x213c3d17, 0x0000000f,

	0x30000610, 0x00000ff6, 0x10000110, 0x20000010,			/* 41, unlock,  */
	0x00027106, 0x10000510, 0x20000111, 0x00001228,
	0x33ffff27, 0x340f0ff7, 0x2d003d17, 0x0000000f,
};


int  nor_flash_init( uint32_t sp, uint32_t sb )
{
	int  i;
	uintptr_t  pbase;

	/**/
	spage = sp;
	sblck = sb;

	/* read: 3 byte addr, page size */
	sf_inst_reg_set_bytes( &insts[1], 3);
	sf_inst_fifo_mod( &insts[2], spage );

	/* erase: Write Enable(06h), Sector Erase (20h), 3 byte addr */
	sf_inst_tmp_set( &insts[4+0], (uint32_t)0x06, 1);
	sf_inst_tmp_set( &insts[4+2], (uint32_t)0x20, 1);
	sf_inst_reg_set_bytes( &insts[4+3], 3 );

	/* prog: 3 byte addr,  page size */
	sf_inst_reg_set_bytes( &insts[16+3], 3);
	sf_inst_fifo_mod( &insts[16+4], spage );

	/* lock : Write Enable(06h) */
	sf_inst_tmp_set( &insts[29+0], (uint32_t)0x06, 1 );

	/* unlock : Write Enable(0x06) */
	sf_inst_tmp_set( &insts[41+0], (uint32_t)0x06, 1 );

	/**/
	pbase = BASE_AP_FLASH;

	/**/
	for ( i=0; i < 54; i++ )
	{
		write_reg( pbase + SF_RAMS_ADDR + (i<<2), insts[i] );
	}

	return 0;
}


